package com.lzs.common.utils.valid;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lzs.common.exception.LzsBusinessException;
import org.apache.commons.collections.MapUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.*;

/**
 * 自定义的bean的校验工具  用的是hibernate 的validator工具
 */
public class BeanValidator {

    //自定义一个校验工厂
    private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

    /**
     * 用来校验一个普通的实体类的方法
     * @param t
     * @param clazz
     * @param <T>
     * @return
     */
    private static  <T>Map<String,String> validate(T t,Class... clazz){
        //获得到校验器
        Validator validator = validatorFactory.getValidator();
        //执行校验
        Set<ConstraintViolation<T>> validateResult = validator.validate(t, clazz);
        //判断set集合是否为空 如果不为空的话就代表的是bean的字段有错误
        if(!validateResult.isEmpty()){//此时有错误
            //定义一个map用来接收所有的错误信息
            LinkedHashMap<String,String> errorsMap = Maps.newLinkedHashMap();
            for (ConstraintViolation violation : validateResult) {//遍历获得到此对象
                errorsMap.put(violation.getPropertyPath().toString(),violation.getMessage());//将字段和错误信息封装到自己的map中
            }
            return errorsMap;
        }
        //如果没有错误直接放回一个空的map
        return Collections.emptyMap();//返回一个空的map
    }

    /**
     * 用来校验一个集合的方法
     * @param collections
     * @return
     */
    private static Map<String,String> validateList(Collection<?> collections){
        //首先进行校验 看传入的集合是否为空
        Preconditions.checkNotNull(collections);
        //先声明一个错误的map集合
        IdentityHashMap<String,String> errors = Maps.newIdentityHashMap();
        //对collections进行遍历
        int i=0;
        for (Object obj : collections) {
            if(obj==null){
                errors.put(i+"","此项是个空值");
                continue;
            }
            //直接调用上面的方法
            Map<String, String> validate = validate(obj, new Class[0]);
            errors.putAll(validate);
        }
        return errors;
    }



    /**
     * 公用的一个校验的方法
     * @param object
     * @param objects
     * @return
     */
    private static Map<String,String> validateObject(Object object,Object... objects){
        //判断第二个可变参数是否为空
        if(objects!=null && objects.length>0){//此时是有多个参数的
            return validateList(Lists.asList(object,objects));//将形参全部做成一个集合 进行校验
        }
        //到这里时只有一个参数
        return validate(object,new Class[0]);
    }

    /**
     * 用来校验并且抛出异常的方法
     * @param object
     * @param objects
     */
    public static void check(Object object,Object... objects){
        Map<String, String> validateResultMap = validateObject(object, objects);
        if(MapUtils.isNotEmpty(validateResultMap)){//此时是有错误的
            if (validateResultMap.size()==1){
                for (String key : validateResultMap.keySet()) {
                    throw new LzsBusinessException(validateResultMap.get(key));
                }
            }
            throw new LzsBusinessException(JSON.toJSONString(validateResultMap));
        }
    }

}
